#pragma once
#include <array>
#include <complex>
#include <string>
#include <vector>
#include <libmesh/numeric_vector.h>

namespace cem
{

class ElectromagneticsSystem;
class ParameterReader;

// PostProcessor 负责结果后处理与导出（脚手架阶段不写文件）。
class PostProcessor
{
public:
    // 函数: write_basic_log
    // 作用: 输出基本日志（占位）。
    // 参数: system - 电磁系统引用
    // 返回: 无
    void write_basic_log(const ElectromagneticsSystem & system) const;

    // 函数: write_vtk_snapshot
    // 作用: 将当前方程系统的解导出为 VTK 文件（.vtk），用于可视化与调试。
    // 参数:
    //   system: 电磁系统引用（内部持有 EquationSystems 和解向量）
    //   filename: 输出文件名（建议以 .vtk 结尾，写入当前工作目录）
    // 返回: 无
    void write_vtk_snapshot(const ElectromagneticsSystem & system,
                            const std::string & filename) const;

    // 函数: write_solution_csv
    // 作用: 将解向量以 CSV 文本格式写出（两列: index,value_real,value_imag）。
    // 说明: 若底层标量为实数类型，则 value_imag 恒为 0；并行环境中仅 rank 0 写文件。
    // 参数:
    //   system  : 电磁系统引用
    //   filename: 输出文件路径（建议以 .csv 结尾）
    // 返回: 无
    void write_solution_csv(const ElectromagneticsSystem & system,
                            const std::string & filename) const;

    // 函数: write_mt_csv
    // 作用: 按有限元解在参数指定的 COLLECT_POINT 采样点处，
    //       插值电场 E 与其旋度 curl(E)，以 H = i/(ωμ) curl(E) 得到磁场，
    //       进一步计算 MT 阻抗 Zxy = Ex/Hy 与 Zyx = Ey/Hx，
    //       输出列: num,x0_loc,y0_loc,z0_loc,xy_ris,yx_ris,alph_xy,alph_yx。
    // 说明: 仅在 rank 0 写出；若点不在本地单元内则当前输出 NaN（后续可做并行聚合）。
    // 参数:
    //   system  : 电磁系统（提供解向量、材料与角频率）
    //   params  : 参数读取器（提供 COLLECT_POINT 采样点集）
    //   filename: 输出 CSV 路径
    // 返回: 无
    void write_mt_csv(const ElectromagneticsSystem & system,
                      const ParameterReader & params,
                      const std::string & filename) const;

    // 函数: write_mt_csv_dual
    // 作用: 使用两套线性独立激励得到的两组解（system_a 与 system_b），
    //       在采样点处分别插值 [Ex,Ey,Hx,Hy]，组装 2×2 线性系统 H，
    //       按 Z = E * H^{-1} 解耦合得到 Zxy 与 Zyx，
    //       并写出视电阻率与相位（与 legacy 的 2×2 解耦合一致）。
    // 说明: 仅在 rank 0 写出；假定两个系统共享同一网格与材料场（常见做法）。
    // 参数:
    //   system_a: 第一套激励对应的电磁系统（例如 x 极化）
    //   system_b: 第二套激励对应的电磁系统（例如 y 极化）
    //   params  : 参数读取器（提供 COLLECT_POINT 采样点集）
    //   filename: 输出 CSV 路径
    // 返回: 无
    void write_mt_csv_dual(const ElectromagneticsSystem & system_a,
                           const ElectromagneticsSystem & system_b,
                           const ParameterReader & params,
                           const std::string & filename) const;

    // 函数: write_mt_csv_dual_from_host
    // 作用: 使用 rank 0 上聚合好的两份全局解数组（与全局 DOF 编号一致），
    //       直接按 DOF 索引取值进行 2×2 解耦合并写出 CSV。
    // 参数:
    //   system : 单个电磁系统（提供 FE 拓扑、材料映射与角频率）
    //   sol_a  : 第一次极化的全局解数组（大小 = n_dofs）
    //   sol_b  : 第二次极化的全局解数组（大小 = n_dofs）
    //   params : 参数读取器（提供 COLLECT_POINT 采样点集）
    //   filename: 输出 CSV 路径
    // 返回: 无
    void write_mt_csv_dual_from_host(
        const ElectromagneticsSystem & system,
        const std::vector<std::complex<double>> & sol_a,
        const std::vector<std::complex<double>> & sol_b,
        const ParameterReader & params,
        const std::string & filename) const;

    // 函数: write_real_part_debug
    // 作用: 在不依赖 legacy 压缩存储的前提下，复现 legacy/solver.c#L122-131 的调试输出：
    //       输出第一批（最多501条）“实部组成项”的诊断信息：
    //       matrix_a_r[i] 与 matrix_a_r2[i]*omega*omega，其中
    //       matrix_a_r 对应 curl(μ^{-1}curl) 的积分项累计，
    //       matrix_a_r2 对应 -∫(ε ϕ_j·ϕ_i) dΩ（取负号以满足 A = K + (matrix_a_r2)*ω²）。
    // 说明: 仅 rank 0 写出，文件格式与 legacy 一致：
    //       i= <i>, matrix_a_r[<i>]= <val1>, matrix_a_r2[<i>]*omega*omega= <val2>
    // 参数:
    //   system  : 电磁系统（提供材料映射与角频率）
    //   filename: 输出文件名（建议 Real_part.txt）
    // 返回: 无
    void write_real_part_debug(const ElectromagneticsSystem & system,
                               const std::string & filename) const;
};

} // namespace cem